﻿using System;
using System.Xml;
using System.Collections.Generic;
using System.Reflection;
using System.Text;

namespace Tools.InfoStorage
{
    /// <summary>
    /// XmlHelper 的摘要说明
    /// </summary>
    public class XmlPlus
    {
        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="xdoc"></param>
        /// <param name="path"></param>
        /// <returns>string</returns>
        public static XmlNodeList ReadNodes(XmlDocument xdoc, string path)
        {
            var nodes = xdoc.SelectSingleNode(path);
            return nodes.ChildNodes;
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="xn">节点</param>
        /// <param name="node">节点</param>
        /// <param name="attribute">属性名，非空时返回该属性值，否则返回串联值</param>
        /// <returns>string</returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.Read(xn, "Node", "")
         * XmlHelper.Read(xn, "Node", "Attribute")
         ************************************************/
        public static string Read(XmlNode xn, string node, string attribute)
        {
            string value = "";
            var _xn = xn.SelectSingleNode(node);
            if (_xn != null)
                if (_xn.Attributes != null)
                    value = (attribute.Equals("") ? _xn.InnerText : _xn.Attributes[attribute].Value);
            return value;
        }

        /// <summary>
        /// 读取数据
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="node">节点</param>
        /// <param name="attribute">属性名，非空时返回该属性值，否则返回串联值</param>
        /// <returns>string</returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.Read(path, "/Node", "")
         * XmlHelper.Read(path, "/Node/Element[@Attribute='Name']", "Attribute")
         ************************************************/
        public static string Read(string path, string node, string attribute)
        {
            string value = "";
            var doc = new XmlDocument();
            doc.Load(path);
            XmlNode xn = doc.SelectSingleNode(node);
            if (xn != null)
                if (xn.Attributes != null)
                    value = (attribute.Equals("") ? xn.InnerText : xn.Attributes[attribute].Value);
            return value;
        }

        public static string Read(XmlDocument doc, string node, string attribute)
        {
            string value = "";
            XmlNode xn = doc.SelectSingleNode(node);
            if (xn != null)
                if (xn.Attributes != null)
                    value = (attribute.Equals("") ? xn.InnerText : xn.Attributes[attribute].Value);
            return value;
        }
        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="node">节点</param>
        /// <param name="element">元素名，非空时插入新元素，否则在该元素中插入属性</param>
        /// <param name="attribute">属性名，非空时插入该元素属性值，否则插入元素值</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.Insert(path, "/Node", "Element", "", "Value")
         * XmlHelper.Insert(path, "/Node", "Element", "Attribute", "Value")
         * XmlHelper.Insert(path, "/Node", "", "Attribute", "Value")
         ************************************************/
        public static void Insert(string path, string node, string element, string attribute, string value)
        {
            var doc = new XmlDocument();
            doc.Load(path);
            XmlNode xn = doc.SelectSingleNode(node);
            if (element.Equals(""))
            {
                if (!attribute.Equals(""))
                {
                    var xe = (XmlElement)xn;
                    if (xe != null) xe.SetAttribute(attribute, value);
                }
            }
            else
            {
                XmlElement xe = doc.CreateElement(element);
                if (attribute.Equals(""))
                    xe.InnerText = value;
                else
                    xe.SetAttribute(attribute, value);
                if (xn != null) xn.AppendChild(xe);
            }
            doc.Save(path);
        }

        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="node">节点</param>
        /// <param name="attribute">属性名，非空时修改该节点属性值，否则修改节点值</param>
        /// <param name="value">值</param>
        /// <returns></returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.Insert(path, "/Node", "", "Value")
         * XmlHelper.Insert(path, "/Node", "Attribute", "Value")
         ************************************************/
        public static void Update(string path, string node, string attribute, string value)
        {
            var doc = new XmlDocument();
            doc.Load(path);
            XmlNode xn = doc.SelectSingleNode(node);
            var xe = (XmlElement)xn;
            if (attribute.Equals(""))
            {
                if (xe != null) xe.InnerText = value;
            }
            else if (xe != null) xe.SetAttribute(attribute, value);
            doc.Save(path);
        }

        /// <summary>
        /// 删除数据
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="node">节点</param>
        /// <param name="attribute">属性名，非空时删除该节点属性值，否则删除节点值</param>
        /// <returns></returns>
        /**************************************************
         * 使用示列:
         * XmlHelper.Delete(path, "/Node", "")
         * XmlHelper.Delete(path, "/Node", "Attribute")
         ************************************************/
        public static void Delete(string path, string node, string attribute)
        {
            var doc = new XmlDocument();
            doc.Load(path);
            XmlNode xn = doc.SelectSingleNode(node);
            var xe = (XmlElement)xn;
            if (attribute.Equals(""))
            {
                if (xn != null) if (xn.ParentNode != null) xn.ParentNode.RemoveChild(xn);
            }
            else if (xe != null) xe.RemoveAttribute(attribute);
            doc.Save(path);

        }


        /// <summary>
        /// 实体类序列化成xml
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="headtag">The headtag.</param>
        /// <returns></returns>
        public static string ObjListToXml(object obj, string headtag)
        {
            var enitities = new List<object> { obj };
            return ObjListToXml(enitities, headtag);
        }
        #region 实体类，XML互操作
        /// <summary>
        /// 实体类序列化成xml
        /// </summary>
        /// <param name="enitities">The enitities.</param>
        /// <param name="headtag">The headtag.</param>
        /// <returns></returns>
        public static string ObjListToXml<T>(List<T> enitities, string headtag)
        {
            var sb = new StringBuilder();
            PropertyInfo[] propinfos = null;
            sb.AppendLine("<?xml version=\"1.0\" encoding=\"utf-8\"?>");
            sb.AppendLine("<" + headtag + ">");
            foreach (T obj in enitities)
            {
                //初始化propertyinfo
                if (propinfos == null)
                {
                    Type objtype = obj.GetType();
                    propinfos = objtype.GetProperties();
                }
                foreach (PropertyInfo propinfo in propinfos)
                {
                    sb.Append("<");
                    sb.Append(propinfo.Name);
                    sb.Append(">");
                    sb.Append(propinfo.GetValue(obj, null));
                    sb.Append("</");
                    sb.Append(propinfo.Name);
                    sb.AppendLine(">");
                }
            }
            sb.AppendLine("</" + headtag + ">");
            return sb.ToString();
        }

        /// <summary>
        /// 使用XML初始化实体类容器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml">The XML.</param>
        /// <param name="headtag">The headtag.</param>
        /// <returns></returns>
        public static List<T> XmlToObjList<T>(string xml, string headtag)
            where T : new()
        {
            var list = new List<T>();
            var doc = new XmlDocument();
            PropertyInfo[] propinfos = null;
            doc.LoadXml(xml);
            XmlNodeList nodelist = doc.SelectNodes("/" + headtag);
            if (nodelist != null)
                foreach (XmlNode node in nodelist)
                {
                    var entity = new T();
                    //初始化propertyinfo
                    if (propinfos == null)
                    {
                        Type objtype = entity.GetType();
                        propinfos = objtype.GetProperties();
                    }
                    //填充entity类的属性
                    foreach (PropertyInfo propinfo in propinfos)
                    {
                        XmlNode cnode = node.SelectSingleNode(propinfo.Name);
                        if (cnode != null)
                        {
                            string v = cnode.InnerText;
                            propinfo.SetValue(entity, Convert.ChangeType(v, propinfo.PropertyType), null);
                        }
                    }
                    list.Add(entity);
                }
            return list;
        }
        #endregion
    }
}
